﻿/*
 *  Date:2015/8/4
 *  Author: huang hao
 */
using IceCS.Puke.Core.PukeEventHandler;
using IceCS.Puke.Core.PukeException;
using System;

namespace IceCS.Puke.Core
{
    /// <summary>
    /// 表示一副完整（52张）的扑克牌，在扑克牌中可以按照位置访问各张牌，并可以洗牌
    /// </summary>
    public class Deck : ICloneable
    {
        /// <summary>
        /// 定义一个card 的集合对象
        /// </summary>
        private readonly CardList _cardList;

        #region 构造函数
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public Deck()
        {
            _cardList = new CardList(52);

            for (int i = 1; i <= 4; i++)
            {
                for (int j = 1; j <= 13; j++)
                {
                    _cardList.Add(new Card((Suit)i, (Rank)j));
                }
            }
        }

        /// <summary>
        /// 自定义构造函数
        /// </summary>
        /// <param name="isAceHigh">判断A点是比K大还是比2小，如果是true，则是最大的牌，否则是最小的牌</param>
        public Deck(bool isAceHigh) : this()
        {
            IsAceHigh = isAceHigh;
        }

        /// <summary>
        /// 自定义构造函数
        /// </summary>
        /// <param name="useTrump">使用王牌花色</param>
        /// <param name="trump">设置王牌花色(即在花色不同的情况下，此花色比其他的花色大，牌面符号大小无用)</param>
        public Deck(bool useTrumps, Suit trump) : this()
        {
            UseTrumps = useTrumps;
            Trump = trump;
        }

        /// <summary>
        /// 自定义构造函数
        /// </summary>
        /// <param name="isAceHigh">判断A点是比K大还是比2小，如果是true，则是最大的牌，否则是最小的牌</param>
        /// <param name="useTrump">使用王牌花色</param>
        /// <param name="trump">设置王牌花色(即在花色不同的情况下，此花色比其他的花色大，牌面符号大小无用)</param>
        public Deck(bool isAceHigh, bool useTrumps, Suit trump) : this()
        {
            IsAceHigh = isAceHigh;
            UseTrumps = useTrumps;
            Trump = trump;
        }

        /// <summary>
        /// 私有构造函数，用于克隆牌堆
        /// </summary>
        /// <param name="list"></param>
        private Deck(CardList list)
        {
            _cardList = list;
        }

        #endregion

        #region 判断用的静态变量

        /// <summary>
        /// 使用王牌花色
        /// </summary>
        public static bool UseTrumps { get; private set; } = false;

        /// <summary>
        /// 设置王牌花色(即在花色不同的情况下，此花色比其他的花色大，牌面符号大小无用)
        /// </summary>
        public static Suit Trump { get; private set; } = Suit.Spade;

        /// <summary>
        /// 判断A点是比K大还是比2小，如果是true，则是最大的牌，否则是最小的牌
        /// </summary>
        public static bool IsAceHigh { get; private set; } = false;
        #endregion

        #region 定义事件

        /// <summary>
        /// 最后一张卡牌获取的事件
        /// </summary>
        public event EventHandler<LastCardDrawnEventArgs> LastCardDrawn;

        #endregion

        /// <summary>
        /// 获取一张扑克,扑克牌的序号，参数在（1-52）之间,包含1和52
        /// </summary>
        /// <param name="index">卡牌索引</param>
        /// <returns></returns>
        public Card GetCard(int index)
        {
            if (index >= 1 && index <= 52)
            {
                var card = _cardList[index - 1];
                if (index == 52 && LastCardDrawn != null)
                {
                    //通知获取最后一张牌的事件
                    LastCardDrawn?.Invoke(this, new LastCardDrawnEventArgs(card));
                }
                return card;
            }
            else
            {
                throw new CardOutOfRangeException(index);
            }
        }
        /// <summary>
        /// 进行洗牌操作
        /// </summary>
        public void Shuffle()
        {
            _cardList.Shuffle();
        }

        /// <summary>
        /// 复制一副扑克牌
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            Deck deck = new Deck(_cardList.Clone() as CardList);
            return deck;
        }
    }
}
